package service

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/tidwall/gjson"
	"gorm.io/gorm"
	"io/ioutil"
	"net/http"
	"net/url"
	"path"
	"strconv"
	"strings"
	"time"
	"vrcm/src/vrcm/app/admin/models"
	"vrcm/src/vrcm/app/admin/models/live"
	dto "vrcm/src/vrcm/app/admin/service/dto/live"
	"vrcm/src/vrcm/common/service"
	ext "vrcm/src/vrcm/envconfig"
)

type LiveRecord struct {
	service.Service
}

// StartLiveRecord 开始录制
func (e *LiveRecord) StartLiveRecord(tx *gorm.DB, d *dto.StartRecordReq) error {

	if err := tx.Error; err != nil {
		return err
	}

	//根据基本信息id获取直播流信息
	var record live.LiveMonitorRecord
	e.Orm.Model(&live.LiveMonitorRecord{}).Where("tenant_id = ? and basic_id = ? and is_delete = 2", d.TenantId, d.BasicId).Find(&record)
	if record.Id <= 0 {
		return errors.New("未找到直播间信息")
	}

	//请求录制接口
	params := url.Values{}
	urlString := ext.ExtConfig.ServiceConfig.NgvsaServiceUrl + "/v1/live_record"
	Url, err := url.Parse(urlString)
	if err != nil {
		return err
	}
	params.Set("tenant_id", d.TenantId)
	Url.RawQuery = params.Encode()
	urlPath := Url.String()

	// 参数
	data := make(map[string]interface{})
	data["record_name"] = d.RecordName
	data["live_id"] = record.LiveId
	data["start_time"] = time.Now().Unix()
	data["end_time"] = time.Now().AddDate(0, 0, 3).Unix()
	// Marshal
	bytesData, _ := json.Marshal(data)
	// 获取 request请求
	request, err := http.NewRequest("POST", urlPath, bytes.NewReader(bytesData))
	if len(ext.ExtConfig.ServiceConfig.VsApiServiceUrl) > 0 {
		request.Header.Set("Authorization", "Bearer "+models.SuperToken)
		request.Header.Set("X-PS-Flag", "")
	} else {
		request.Header.Set("Authorization", "vsnb")
	}
	request.Header.Add("Content-Type", "application/json")
	if err != nil {
		e.Log.Errorf("GetHttpSkip Request Error:", err)
		return nil
	}

	response, err := client.Do(request)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Response Error:", err)
		return err
	}

	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		e.Log.Errorf("读取响应体失败 error:%s", err)
		return err
	}
	e.Log.Trace("StartLiveRecord:", string(body))
	result := gjson.Parse(string(body))
	if result.Get("code").String() == "170002" {
		return errors.New("170002")
	}
	if result.Get("code").String() != "200" {
		return errors.New(result.Get("message").String())
	}

	//存储录制任务
	taskId := result.Get("data").Get("id").String()
	now := time.Now().Unix()
	var task live.RecordTask
	task.TenantId = record.TenantId
	task.LiveId = record.LiveId
	task.TaskId = taskId
	task.TaskState = 1
	task.CreateBy = d.CreateBy
	task.CreateTime = now
	task.UpdateTime = now
	task.IsDelete = 2
	err = tx.Model(&live.RecordTask{}).Create(&task).Error
	if err != nil {
		tx.Rollback()
		e.Log.Errorf("创建录制任务记录失败 error:%s", err)
		return err
	}

	err = tx.Model(&live.LiveBasic{}).Where("id=?", d.BasicId).Update("task_id", taskId).Error
	if err != nil {
		tx.Rollback()
		e.Log.Errorf("更新录制任务id失败 error:%s", err)
		return err
	}
	tx.Commit()
	return nil
}

// StopLiveRecord 结束录播
func (e *LiveRecord) StopLiveRecord(d *dto.StopRecordReq) error {

	params := url.Values{}
	urlString := ext.ExtConfig.ServiceConfig.NgvsaServiceUrl + "/v1/live_record/"
	//通过基本信息id获取直播流信息
	var record live.LiveMonitorRecord
	e.Orm.Model(&live.LiveMonitorRecord{}).Where("tenant_id = ? and basic_id = ? and is_delete = 2", d.TenantId, d.BasicId).Find(&record)
	if record.Id <= 0 {
		return errors.New("未找到直播流信息")
	}

	//找到直播录制中状态的数据
	var task live.RecordTask
	e.Orm.Model(&live.RecordTask{}).Where("tenant_id = ? and live_id = ? and is_delete = 2 and task_state =1", record.TenantId, record.LiveId).Find(&task)
	if task.Id <= 0 {
		return errors.New("未找到正在录制的任务")
	}
	//拼接请求地址
	urlString = urlString + task.TaskId + "/stop"
	Url, err := url.Parse(urlString)
	if err != nil {
		return err
	}
	params.Set("tenant_id", d.TenantId)
	Url.RawQuery = params.Encode()
	urlPath := Url.String()
	e.Log.Trace("StopLiveRecord:", urlString)
	// 获取 request请求
	request, err := http.NewRequest("PUT", urlPath, nil)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Request Error:", err)
		return err
	}
	if len(ext.ExtConfig.ServiceConfig.VsApiServiceUrl) > 0 {
		request.Header.Set("Authorization", "Bearer "+models.SuperToken)
		request.Header.Set("X-PS-Flag", "")
	} else {
		request.Header.Set("Authorization", "vsnb")
	}
	response, err := client.Do(request)
	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		e.Log.Errorf("读取响应体失败 error:%s", err)
		return err
	}
	e.Log.Trace("StopLiveRecord:", string(body))
	result := gjson.Parse(string(body))
	code := result.Get("code").Int()
	//170007 已经结束录制的不报错
	if code != http.StatusOK && code != 170007 {
		return errors.New(result.Get("message").String())
	}

	err = e.DeleteLiveRecordTask(&dto.StopRecordReq{TenantId: record.TenantId, BasicId: d.BasicId})
	if err != nil {
		e.Log.Errorf("删除录制任务失败： Error:", err)
		return err
	}

	//将录制任务状态设置为结束录制
	err = e.Orm.Model(&live.RecordTask{}).Where("tenant_id = ? and live_id = ? and is_delete = 2 and task_state =1", record.TenantId, record.LiveId).Update("task_state", 2).Error
	if err != nil {
		e.Log.Errorf("更新录制任务状态失败： Error:", err)
		return err
	}

	return nil
}

// DeleteLiveRecordTask 结束录播
func (e *LiveRecord) DeleteLiveRecordTask(d *dto.StopRecordReq) error {

	params := url.Values{}
	urlString := ext.ExtConfig.ServiceConfig.NgvsaServiceUrl + "/v1/live_record/"
	//通过基本信息id获取直播流信息
	var record live.LiveMonitorRecord
	e.Orm.Model(&live.LiveMonitorRecord{}).Where("tenant_id = ? and basic_id = ? and is_delete = 2", d.TenantId, d.BasicId).Find(&record)
	if record.Id <= 0 {
		return errors.New("未找到直播流信息")
	}

	//找到直播录制中状态的数据
	var task live.RecordTask
	e.Orm.Model(&live.RecordTask{}).Where("tenant_id = ? and live_id = ? and is_delete = 2 and task_state =1", record.TenantId, record.LiveId).Find(&task)
	if task.Id <= 0 {
		return errors.New("未找到正在录制的任务")
	}
	//拼接请求地址
	urlString = urlString + task.TaskId
	Url, err := url.Parse(urlString)
	if err != nil {
		return err
	}
	params.Set("tenant_id", d.TenantId)
	Url.RawQuery = params.Encode()
	urlPath := Url.String()
	e.Log.Trace("DeleteLiveRecordTask:", urlString)
	// 获取 request请求
	request, err := http.NewRequest("DELETE", urlPath, nil)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Request Error:", err)
		return err
	}
	if len(ext.ExtConfig.ServiceConfig.VsApiServiceUrl) > 0 {
		request.Header.Set("Authorization", "Bearer "+models.SuperToken)
		request.Header.Set("X-PS-Flag", "")
	} else {
		request.Header.Set("Authorization", "vsnb")
	}
	response, err := client.Do(request)
	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		e.Log.Errorf("读取响应体失败 error:%s", err)
		return err
	}
	e.Log.Trace("DeleteLiveRecordTask:", string(body))
	result := gjson.Parse(string(body))
	code := result.Get("code").Int()
	//170007 已经结束录制的不报错
	if code != http.StatusOK && code != 170007 {
		return errors.New(result.Get("message").String())
	}

	return nil
}

// GetLiveRecord 查询直播
func (e *LiveRecord) GetLiveRecord(d *live.RecordTask) (string, error) {

	params := url.Values{}
	urlString := ext.ExtConfig.ServiceConfig.NgvsaServiceUrl + "/v1/cloud_live/"
	//拼接请求地址
	urlString = urlString + d.TaskId
	Url, err := url.Parse(urlString)
	if err != nil {
		return "", err
	}

	params.Set("tenant_id", d.TenantId)
	Url.RawQuery = params.Encode()
	urlPath := Url.String()
	fmt.Println(urlPath)
	// 获取 request请求
	request, err := http.NewRequest("GET", urlPath, nil)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Request Error:", err)
		return "", err
	}
	if len(ext.ExtConfig.ServiceConfig.VsApiServiceUrl) > 0 {
		request.Header.Set("Authorization", "Bearer "+models.SuperToken)
		request.Header.Set("X-PS-Flag", "")
	} else {
		request.Header.Set("Authorization", "vsnb")
	}
	response, err := client.Do(request)
	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		e.Log.Errorf("读取响应体失败 error:%s", err)
		return "", err
	}
	result := gjson.Parse(string(body))
	if result.Get("code").Int() != http.StatusOK {
		return "", errors.New(result.Get("message").String())
	}

	status := result.Get("code").Get("status").String()
	return status, nil
}

// DeleteLiveRecord 删除录制
func (e *LiveRecord) DeleteLiveRecord(d *dto.DeleteRecordReq) error {

	//请求录制接口
	urlPath := ext.ExtConfig.ServiceConfig.NgvsaServiceUrl + "/v1/live_record/files/" + d.FileId
	e.Log.Trace("DeleteLiveRecord url:", urlPath)

	// 获取 request请求
	request, err := http.NewRequest("DELETE", urlPath, nil)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Request Error:", err)
		return nil
	}
	if len(ext.ExtConfig.ServiceConfig.VsApiServiceUrl) > 0 {
		request.Header.Set("Authorization", "Bearer "+models.SuperToken)
		request.Header.Set("X-PS-Flag", "")
	} else {
		request.Header.Set("Authorization", "vsnb")
	}
	response, err := client.Do(request)
	if err != nil {
		e.Log.Errorf("GetHttpSkip Response Error:", err)
		return err
	}

	defer response.Body.Close()
	body, err := ioutil.ReadAll(response.Body)
	if err != nil {
		e.Log.Errorf("读取响应体失败 error:%s", err)
		return err
	}
	result := gjson.Parse(string(body))
	if result.Get("code").String() != "200" {
		return errors.New(result.Get("message").String())
	}
	return nil
}

func (e *LiveRecord) RecordFileCallBack(c *dto.RecordFileCallBack) error {

	//获取信源
	var basic live.LiveBasic
	err := e.Orm.Model(live.LiveBasic{}).Where("task_id=?", c.TaskId).Find(&basic).Error
	if err != nil {
		e.Log.Errorf("get LiveBasic error:%s \r\n", err)
		return err
	}

	var count int64
	err = e.Orm.Model(&live.RecordListView{}).Where("basic_id =?", basic.Id).Count(&count).Error
	if err != nil {
		e.Log.Errorf("RecordListViewService getCount error:%s \r\n", err)
		return err
	}
	now := time.Now().Unix()
	startTime, _ := strconv.Atoi(c.StartTime)
	duration, _ := strconv.Atoi(c.Duration)
	if basic.IsConfirm == 1 {
		s := live.RecordListView{}
		s.TenantId = basic.TenantId
		s.BasicId = basic.Id
		s.LiveId = c.LiveId
		//s.FileId = value.Get("id").String()
		s.TaskId = c.TaskId
		s.RecordId = c.FileId
		s.RecordUrl = c.Path
		s.FileName = basic.LiveName
		s.FileType = strings.TrimLeft(path.Ext(c.Path), ".")
		s.FileTime = int64(startTime)
		s.Duration = int64(duration)
		s.OperatorType = 1
		s.IsConfirm = basic.IsConfirm
		s.Sort = int(count + 1)
		s.CreateTime = now
		s.UpdateTime = now
		err = e.Orm.Model(&live.RecordListView{}).Create(&s).Error
		if err != nil {
			e.Log.Errorf("create RecordListView error:%s \r\n", err)
			return err
		}
	}
	s := live.RecordList{}
	s.TenantId = basic.TenantId
	s.BasicId = basic.Id
	s.LiveId = c.LiveId
	//s.FileId = value.Get("id").String()
	s.TaskId = c.TaskId
	s.RecordId = c.FileId
	s.RecordUrl = c.Path
	s.FileName = basic.LiveName
	s.FileType = strings.TrimLeft(path.Ext(c.Path), ".")
	s.FileTime = int64(startTime)
	s.Duration = int64(duration)
	//s.OperatorType = 1
	//s.IsConfirm = basic.IsConfirm
	//s.Sort = int(count + 1)
	s.CreateTime = now
	s.UpdateTime = now
	err = e.Orm.Model(&live.RecordList{}).Create(&s).Error
	if err != nil {
		e.Log.Errorf("create RecordListView error:%s \r\n", err)
		return err
	}

	return nil
}
